<template>
  <div
    class="fa-widget-area"
    :class="{ 'is-drag-over': state.isDragOver }"
    @mousedown.left="boxSelection.start"
    @click.left="onClick"
    @dragover.prevent="state.isDragOver = true"
    @dragleave.prevent="state.isDragOver = false"
    @drop="onDrop($event, $el)"
  >
    <Component
      v-for="item in widgets"
      :is="item.component"
      :key="item.id"
      :data="item"
      :class="{ 'is-selecting': boxSelection.isWidgetInRange(item) }"
    />

    <slot />

    <div
      class="selection-box"
      v-if="boxSelection.enabled"
      v-show="boxSelection.visible"
      :style="boxSelection.style"
    ></div>

    <Transition name="fa-widget__fade">
      <div class="batch-range" v-if="batchRangeStyle" :style="batchRangeStyle"></div>
    </Transition>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, inject, reactive, PropType, toRef, provide, getCurrentInstance, ref } from 'vue'
import { PageData, Viewer, DocData } from '@/types'
import { Widget } from '@/models'
import { EffectLock } from '@/utils'
import useBoxSelection from './useBoxSelection'
import emitWidgetsClick from './emitWidgetsClick'

export default defineComponent({
  name: 'FaWidgetArea',

  props: {
    /** 文档信息 */
    doc: {
      type: Object as PropType<DocData>,
      required: true
    },

    /** 页码数据 */
    page: {
      type: Object as PropType<PageData>,
      required: true
    }
  },

  setup(props) {
    /** 合同控件 */
    const viewer = inject('Viewer') as Viewer

    /** 控件拖拽和调整大小锁 */
    const DnsLocker = inject('DnsLocker') as EffectLock

    /** 控件区域 */
    provide('Area', getCurrentInstance()?.proxy)

    /** 当前页控件 */
    const widgets = computed(() => {
      const { id: docId } = props.doc
      const { p } = props.page

      // 当前页的控件、排除非已完成的骑缝控件
      return viewer.widgets.filter(item => item.isInPage(p, docId) && !(item.isRiding && !item.isDone))
    })

    /** 状态 */
    const state = reactive({
      isDragOver: false // 是否拖拽悬浮
    })

    /** 框选 */
    const boxSelection = useBoxSelection(toRef(props, 'page'), widgets)

    /** 显示范围的批量控件 */
    const batchRangeWidget = ref<Widget | null>(null)

    /** 控件是否处于坐标点上 */
    function isWidgetInPoint(widget: Widget, px: number, py: number) {
      let {
        x,
        y,
        displayWidth: w,
        h,
        isRidingStyle,
        page: { w: pw }
      } = widget

      if (isRidingStyle) {
        x = pw - w
      }

      const isInX = x <= px && x + w >= px
      const isInY = y <= py && y + h >= py

      return isInX && isInY
    }

    /** 拖入控件 */
    async function onDrop(e: DragEvent, area: Element) {
      let data = Widget.getWidgetTransfer(e, area, viewer.zoom.level)

      if (!data || !viewer.droppable) return

      const { id: docId } = props.doc
      const { p } = props.page

      state.isDragOver = false

      const widget = new Widget({ ...data, docId, p })

      await viewer.beforeWidgetDrop?.(widget)

      viewer.addWidget(widget)

      viewer.$emit('widget-drop', widget)

      viewer.activeWidgetId = widget.id
    }

    return {
      /** 当前页控件 */
      widgets,

      /** 状态 */
      state,

      /** 框选 */
      boxSelection,

      /** 显示范围的批量控件 */
      batchRangeWidget,

      /** 批量控件范围 */
      batchRangeStyle: computed(() => {
        const widget = batchRangeWidget.value

        if (!widget) return

        const { minWidth, minHeight } = widget.pageRange

        return {
          width: `${minWidth}px`,
          height: `${minHeight}px`
        }
      }),

      /** 页面点击 */
      onClick(e: MouseEvent) {
        if (DnsLocker.locked) return

        emitWidgetsClick(e, widgets.value, viewer, isWidgetInPoint)
      },

      /** 拖入控件 */
      onDrop
    }
  }
})
</script>

<style lang="scss">
.fa-widget-area {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;

  .selection-box,
  .batch-range {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 10;
    box-sizing: border-box;
    pointer-events: none;
  }

  .selection-box {
    background: rgba($color-primary, 0.05);
    border: 1px solid $color-primary;
  }

  .batch-range {
    background: rgba(241, 245, 255, 0.2);
    border: 1px dashed $color-primary;
    box-shadow: 0px 4px 16px rgba(39, 110, 249, 0.08);

    &.fa-widget__fade {
      &-enter-active,
      &-leave-active {
        transition-duration: 0.3s;
      }
    }
  }

  .fa-widget.is-riding {
    right: 0;
  }
}
</style>
